home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
SciAn
/
src
/
ScianTQ2026F.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
448 lines
/*
* ScianTQ2026F.c
* Written by Marvin Landis
* April 10, 1992
* Controls the Panasonic TQ-2026F optical disk recorder
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianWindows.h"
#include "ScianDialogs.h"
#include "ScianIDs.h"
#include "ScianErrors.h"
#include "ScianTQ2026F.h"
#include "ScianRecorders.h"
#ifdef TERMIO
/* Internal prototypes */
#ifdef PROTO
void TQ_ReportError(int, char *);
void TQ_SendCmd(int, char *);
static int TQ_OpenPort(char *, int);
static int TQ_VerifyResponse(int, char *, int);
static ObjPtr ConnectTQ2026F(ObjPtr);
static ObjPtr PrepareToRecordTQ2026F(ObjPtr, long);
static ObjPtr StopRecordingTQ2026F(ObjPtr);
static ObjPtr DisconnectTQ2026F(ObjPtr);
static ObjPtr SnapOneFrameTQ2026F(ObjPtr);
#endif
void TQ_ReportError(error, procName)
/* Reports the error returned from the TQ_VerifyResponse function */
int error;
char *procName;
{
switch (error) {
case -100:
ReportError(procName, "STX not received");
break;
case -101:
ReportError(procName, "Completion response is invalid");
break;
case -102:
ReportError(procName, "Timeout error");
break;
default:
ReportError(procName, "NAK received from recorder");
break;
}
}
#ifdef PROTO
static int TQ_OpenPort(char *devName, int baudRate)
#else
static int TQ_OpenPort(devName, baudRate)
char *devName;
int baudRate;
#endif
/* Opens a port to the recorder, returns it if successful */
{
int portDev;
struct termio ioStuff;
portDev = open(devName, O_RDWR | O_NDELAY | O_EXCL);
if (portDev < 0)
{
return portDev;
}
ioctl(portDev, TCGETA, &ioStuff);
ioStuff . c_oflag = 0;
ioStuff . c_iflag = IGNBRK;
ioStuff . c_lflag &= ~( ICANON | ECHO );
/*Make cflag from baud rate*/
switch(baudRate)
{
case RB_300:
ioStuff . c_cflag = (unsigned short) (B300 | CS8 | CLOCAL | CREAD | CSTOPB);
break;
case RB_1200:
ioStuff . c_cflag = (unsigned short) (B1200 | CS8 | CLOCAL | CREAD);
break;
case RB_2400:
ioStuff . c_cflag = (unsigned short) (B2400 | CS8 | CLOCAL | CREAD);
break;
case RB_4800:
ioStuff . c_cflag = (unsigned short) (B4800 | CS8 | CLOCAL | CREAD);
break;
case RB_9600:
ioStuff . c_cflag = (unsigned short) (B9600 | CS8 | CLOCAL | CREAD);
break;
case RB_19200:
ioStuff . c_cflag = (unsigned short) (B19200 | CS8 | CLOCAL | CREAD);
break;
}
ioStuff . c_cc[4] = 1;
ioStuff . c_cc[0] = 1;
ioctl(portDev, TCSETA, &ioStuff);
return portDev;
}
void TQ_SendCmd(portDev, command)
/* Encapsulates the command in a STX / ETX pair, then sends the command
* to the recorder.
*/
int portDev;
char *command;
{
char fullcommand[256];
int bytesWritten;
sprintf(fullcommand, "%c%s%c", STX, command, ETX);
bytesWritten = write(portDev, fullcommand, strlen(fullcommand));
}
static int TQ_VerifyResponse(portDev, command, timeout)
/* Reads the completion response from the recorder, checks to see if it is
* the correct response, and returns the result. Returns either a 0 or a
* positive integer (the number of remaining frames to be recorded, as returned
* from the RECORD_REMAIN command) iff the command is successfully completed.
* Returns the following negative numbers if there was a problem decoding the
* command:
*
* -1 to -99 NAK response error
* -100 STX not received
* -101 Completion response does not match the command
* -102 Timeout
*/
int portDev;
char *command;
int timeout;
{
char retVal[256], fullRetVal[256];
int i, j;
int bytesRead;
int retInt = 0;
long startTime, curTime;
struct tms buffer;
startTime = times(&buffer);
strcpy(fullRetVal, "");
do
{
sleep(1); /* Couldn't get consistent results without this delay */
bytesRead = read(portDev, retVal, 256);
if (bytesRead > 0)
{
retVal[bytesRead] = 0;
strcat(fullRetVal, retVal);
if (fullRetVal[0] != ACK)
{
/* NAK has been received. Decode the error number, and return
* the negative value of the error
*/
j = 0;
while (fullRetVal[++j])
retInt = retInt * 10 + (fullRetVal[j] - '0');
return -retInt;
}
else
{
/* ACK has been received. STX is next, then the completion
* response. Optional number follows, then terminates with
* an ETX.
*/
j = 0;
while (fullRetVal[++j])
{
/* The very first time an ON8: command is sent to the
* recorder, the ACK is followed by a CR/LF. After ON8:
* is executed, there are no more CR/LF's sent. This
* statement takes care of that first CR/LF.
*/
if (fullRetVal[j] == CR) j += 2;
if (fullRetVal[j] != STX) return -100;
if (fullRetVal[++j] == 'E') {
retInt = 0;
while (fullRetVal[++j] != ETX)
retInt = retInt * 10 + (fullRetVal[j] - '0');
retInt = -retInt;
}
else
{
if (fullRetVal[j] != command[0]) return -101;
if (fullRetVal[++j] != command[1]) return -101;
retInt = 0;
while (fullRetVal[++j] != ETX)
retInt = retInt * 10 + (fullRetVal[j] - '0');
return retInt;
}
}
}
}
curTime = times(&buffer);
} while (curTime < startTime + timeout * HEARTBEAT);
return -102;
}
static ObjPtr ConnectTQ2026F(object)
/* Connects to the Panasonic TQ-2026F. Returns true iff successful */
ObjPtr object;
{
int portDev;
int response;
char *devName;
int baudRate;
ObjPtr var;
MakeVar(object, PORTDEV);
var = GetStringVar("ConnectTQ2026F", object, PORTDEV);
if (var)
{
devName = GetString(var);
}
else
{
devName = TQ2026F_DEV;
}
MakeVar(object, BAUDRATE);
var = GetIntVar("ConnectTQ2026F", object, BAUDRATE);
if (var)
{
baudRate = GetInt(var);
}
else
{
baudRate = RB_9600;
}
/*Open the serial port*/
portDev = TQ_OpenPort(devName, baudRate);
if (portDev < 0)
{
return ObjFalse;
}
/*Now that a port is open, connect to it*/
TQ_SendCmd(portDev, ONLINE);
response = TQ_VerifyResponse(portDev, ONLINE, 5);
if (response == 0)
{
/* Exercise the recorder a little to verify it is ready */
TQ_SendCmd(portDev, STEP_FORWARD);
response = TQ_VerifyResponse(portDev, STEP_FORWARD, 20);
if (response == 0)
{
TQ_SendCmd(portDev, STEP_BACKWARD);
response = TQ_VerifyResponse(portDev, STEP_BACKWARD, 5);
if (response == 0) {
SetVar(object, PORTNUMBER, NewInt(portDev));
return ObjTrue;
}
}
}
close(portDev);
TQ_ReportError(response, "ConnectTQ2026F");
return ObjFalse;
}
static ObjPtr PrepareToRecordTQ2026F(object, nFrames)
/* Prepares to record nFrames on an TQ2026F. Returns true iff successful. */
ObjPtr object;
long nFrames;
{
ObjPtr port;
int portDev;
int remFrames;
int response;
char searchCommand[256];
port = GetVar(object, PORTNUMBER);
if (port)
{
portDev = GetInt(port);
do
{
/* Manual record mode searches for next blank recording area. */
TQ_SendCmd(portDev, MANUAL_RECORD_MODE);
response = TQ_VerifyResponse(portDev, MANUAL_RECORD_MODE, 400);
if (response < 0)
{
TQ_ReportError(response, "PrepareToRecordTQ2026F");
return ObjFalse;
}
/* Now find out how many blank frames there are to record on */
TQ_SendCmd(portDev, RECORD_REMAIN);
remFrames = TQ_VerifyResponse(portDev, RECORD_REMAIN, 5);
if (remFrames < 0) {
TQ_ReportError(response, "PrepareToRecordTQ2026F");
return ObjFalse;
}
/* If not enough, prepare to search for more */
if (remFrames < nFrames)
{
TQ_SendCmd(portDev, RECORD_MODE_CLEAR);
response = TQ_VerifyResponse(portDev, RECORD_MODE_CLEAR, 5);
if (response < 0)
{
TQ_ReportError(response, "PrepareToRecordTQ2026F");
return ObjFalse;
}
/* Search to the next recorded frame, then try again */
sprintf(searchCommand, "%s+%d:", SEARCH, remFrames);
TQ_SendCmd(portDev, searchCommand);
response = TQ_VerifyResponse(portDev, SEARCH, 5);
if (response < 0)
{
TQ_ReportError(response, "PrepareToRecordTQ2026F");
return ObjFalse;
}
}
} while (remFrames < nFrames);
return ObjTrue;
}
return ObjFalse;
}
static ObjPtr StopRecordingTQ2026F(object)
/* Stops recording */
ObjPtr object;
{
ObjPtr port;
int response;
port = GetVar(object, PORTNUMBER);
if (port)
{
int portDev;
portDev = GetInt(port);
TQ_SendCmd(portDev, RECORD_MODE_CLEAR);
response = TQ_VerifyResponse(portDev, RECORD_MODE_CLEAR, 5);
if (response == 0)
return ObjTrue;
else
{
TQ_ReportError(response, "StopRecordingTQ2026F");
return ObjFalse;
}
}
return ObjFalse;
}
static ObjPtr DisconnectTQ2026F(object)
/* Takes the recorder offline */
ObjPtr object;
{
int portDev;
ObjPtr port;
int response;
port = GetVar(object, PORTNUMBER);
if (port)
{
portDev = GetInt(port);
TQ_SendCmd(portDev, OFFLINE);
response = TQ_VerifyResponse(portDev, OFFLINE, 5);
if (response == 0)
{
close(portDev);
SetVar(object, PORTNUMBER, NULLOBJ);
return ObjTrue;
}
else
{
TQ_ReportError(response, "DisconnectTQ2026F");
return ObjFalse;
}
}
return ObjFalse;
}
static ObjPtr SnapOneFrameTQ2026F(object)
/* Records one frame on the Panasonic recorder */
ObjPtr object;
{
int portDev;
int response;
ObjPtr port;
port = GetVar(object, PORTNUMBER);
if (port)
{
portDev = GetInt(port);
TQ_SendCmd(portDev, RECORD_FRAME);
response = TQ_VerifyResponse(portDev, RECORD_FRAME, 5);
if (response == 0)
return ObjTrue;
else
{
TQ_ReportError(response, "SnapOneFrameTQ2026F");
return ObjFalse;
}
}
return ObjFalse;
}
#endif
#ifdef PROTO
void InitTQ2026F(void)
#else
void InitTQ2026F()
#endif
/* Return a new TQ-2026F object */
{
#ifdef TERMIO
ObjPtr recorder;
char *devName;
recorder = NewRecorder(commRecorderClass, "TQ-2026F", "Panasonic");
SetMethod(recorder, CONNECT, ConnectTQ2026F);
SetMethod(recorder, DISCONNECT, DisconnectTQ2026F);
SetMethod(recorder, PREPARETORECORD, PrepareToRecordTQ2026F);
SetMethod(recorder, STOPRECORDING, StopRecordingTQ2026F);
SetMethod(recorder, SNAPONEFRAME, SnapOneFrameTQ2026F);
devName = getenv("SCIAN_RECORDER_DEV");
if (!devName || !devName[0])
{
devName = TQ2026F_DEV;
}
SetVar(recorder, PORTDEV, NewString(devName));
RegisterRecorder(recorder);
#endif
}
#ifdef PROTO
void KillTQ2026F(void)
#else
void KillTQ2026F()
#endif
{
}